﻿/*
 * @author: wizardc
 */

using System;
using System.IO;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;

namespace Demo.WorldMap.GPU
{
    /// <summary>
    /// 记录单个资源的信息
    /// 即记录了单个资源的所有位置信息和LOD信息，注意一个资源会包含多个Mesh材质，同时不同的LOD其Mesh材质的组合也不一样
    /// </summary>
    public unsafe class GPUResInfo
    {
        public NativeList<Vector2Int> addRange;
        public NativeList<Vector2Int> removeRange;
        public NativeList<byte> transData;
        
        private GPUStaticRenderRes _res;
        private Stream _dataStream;
        
        private int _lod;
        
        private int _dataLen; // 当前批次的数据量
        
        public int dataLen => _dataLen;
        
        public void Init(GPUStaticRenderRes res, Stream dataStream)
        {
            _res = res;
            _dataStream = dataStream;
            
            addRange = new NativeList<Vector2Int>(Allocator.Persistent);
            removeRange = new NativeList<Vector2Int>(Allocator.Persistent);
            transData = new NativeList<byte>(Allocator.Persistent);
        }
        
        /// <summary>
        /// 设置当前资源的 LOD 等级
        /// </summary>
        public void SetLOD(int lod)
        {
            _lod = lod;
        }
        
        /// <summary>
        /// 获取当前LOD下的所有资源ID
        /// </summary>
        public int[] GetLodIds()
        {
            return _res.lod[_lod].lodId;
        }
        
        /// <summary>
        /// 添加流文件的数据区域
        /// </summary>
        public void AddDataRange(int startIndex, int count)
        {
            _dataLen += count;
            addRange.Add(new Vector2Int(startIndex, count));
        }

        /// <summary>
        /// 移除自身的数据区域
        /// </summary>
        public void RemoveDataRange(int startIndex, int count)
        {
            _dataLen -= count;
            removeRange.Add(new Vector2Int(startIndex, count));
        }
        
        /// <summary>
        /// 从数据流中拷贝对应的数据
        /// </summary>
        public void CopyData()
        {
            // 先删除移除的数据
            if (!removeRange.IsEmpty)
            {
                for (var i = 0; i < removeRange.Length; i++)
                {
                    var remove = removeRange[i];
                    transData.RemoveRange(remove.x, remove.y);
                }
                removeRange.Clear();
            }
            
            // 再添加新增的数据
            if (!addRange.IsEmpty)
            {
                for (var i = 0; i < addRange.Length; i++)
                {
                    var add = addRange[i];
                    var start = add.x;
                    var count = add.y;
                    var len = transData.Length;
                    transData.Length += count;
                    var span = new Span<byte>(transData.GetUnsafePtr() + len, count);
                    _dataStream.Seek(start, SeekOrigin.Begin);
                    _ = _dataStream.Read(span);
                }
                addRange.Clear();
            }
        }
        
        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            addRange.Dispose();
            removeRange.Dispose();
            transData.Dispose();
        }
    }
}
